package com.ocom.ugcapi.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.ocom.common.constant.WxServiceUrl;
import com.ocom.common.entity.card.EntiyXfMerchPayInfo;
import com.ocom.common.entity.company.EntityCompanyConfig;
import com.ocom.common.entity.master.EntityWechatAppInfo;
import com.ocom.common.entity.payconfig.EntityXfSignOrder;
import com.ocom.common.enums.*;
import com.ocom.common.request.payconfig.GzhRefundQueryRequest;
import com.ocom.common.request.payhandle.CheckPayRequest;
import com.ocom.common.request.payhandle.GzhRechageRefundRequest;
import com.ocom.common.request.payhandle.QrCardPayRequest;
import com.ocom.common.request.payhandle.QrCodeRefundRequest;
import com.ocom.common.request.ugcapi.JHcallbackVo;
import com.ocom.common.request.ugcapi.SignCallbackVo;
import com.ocom.common.request.ugcapi.UgcRerchargeRefundRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.*;
import com.ocom.common.vo.pay.CheckVo;
import com.ocom.common.vo.pay.ServiceChargesVo;
import com.ocom.common.vo.simple.ConsumeDetailVo;
import com.ocom.common.vo.ugcapi.GzhUserInfo;
import com.ocom.common.vo.ugcapi.StaticCodePayVo;
import com.ocom.redis.util.RedisUtil;
import com.ocom.ugcapi.client.CompanyClientService;
import com.ocom.ugcapi.client.PayConfigClientService;
import com.ocom.ugcapi.client.PayHandleClientService;
import com.ocom.ugcapi.client.XfRecodeClientService;
import com.ocom.ugcapi.mq.product.ActiveQuiryProduct;
import com.ocom.ugcapi.mq.product.CallbackProducer;
import com.ocom.ugcapi.mq.product.CheckWithholdRefundProduct;
import com.ocom.ugcapi.mq.product.ServiceChargesProduct;
import com.ocom.ugcapi.service.PayService;
import com.ocom.ugcapi.util.Sm2Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@RestController
public class PayController {
    @Autowired
    private PayService payService;

    @Autowired
    CallbackProducer callbackProducer;

    @Autowired
    PayConfigClientService payConfigClientService;


    @Autowired
    XfRecodeClientService xfRecordFeign;

    @Resource
    RedisUtil redisUtil;

    @Autowired
    CompanyClientService companyClientService;

    @Autowired
    private PayHandleClientService payHandleClientService;

    @Autowired
    ServiceChargesProduct serviceChargesProduct;

    @Autowired
    CheckWithholdRefundProduct checkWithholdRefundProduct;

    // 公众号支付（/pay）
    @PostMapping(WxServiceUrl.URL_Pay)
    public Result Pay(@RequestBody Map<String,Object> map){
        Integer type = 1;
        try {
            type = (Integer) map.get("type");
        }catch (Exception e){

        }
        if(type == null   ||  type ==0){
            type = 1;
        }
        Integer subAccount = 0;
        try {
            subAccount = (Integer) map.get("subAccount");
        }catch (Exception e){

        }
        if(subAccount == null){
            subAccount = 0;
        }

        log.info("公众号支付（/pay）请求参数:{{}}",map);
        return payService.Pay((GzhUserInfo)map.get("userInfo"),(Integer) map.get("amount"),type,  Integer.valueOf(map.getOrDefault("consState","10").toString()), Integer.valueOf(map.getOrDefault("feeDataId", "0").toString()),subAccount);
    }

    // 主扫（/StaticCodePay）
    @PostMapping(WxServiceUrl.URL_StaticCodePay)
    public Result StaticCodePay(@RequestBody Map<String, Object> map) {
        //1 普通微信  2 建行 3 轻松付微信
        Integer type = 1;
        try {
            type = (Integer) map.get("type");
        } catch (Exception e) {

        }
        if (type == null || type == 0) {
            type = 1;
        }
        Integer payWay = 1;
        try {
            payWay = (Integer) map.get("payWay");
        } catch (Exception e) {

        }
        log.info("公众号支付（/pay）请求参数:{{}}", map);
        return payService.staticCodePay((GzhUserInfo) map.get("userInfo"),(String) map.get("code"), (Integer) map.get("amount"), type, payWay);
    }

    @PostMapping(WxServiceUrl.URL_AccountPay)
    public Result AccountPay(@RequestBody Map<String,Object> map){
        GzhUserInfo user = (GzhUserInfo) map.get("userInfo");
        if(ObjectUtil.isEmpty(map.get("code"))){
            log.info("AccountPay错误:map参数：【{}】",JSON.toJSONString(map));
            return ResultUtil.error(ResultEnum.Err_900);
        }
        String code = map.get("code").toString();
        Integer amount = (Integer) map.get("amount");
        if(ObjectUtil.isEmpty(amount) || amount <= 0){
            return ResultUtil.error(ResultEnum.Err_5011);
        }
        StaticCodePayVo staticCodePayVo = StaticCodePayUtil.getCodeInfo(code);
        if(ObjectUtil.isEmpty(staticCodePayVo)){
            log.info("AccountPay错误:map参数：【{}】,staticCodePayVo:【{}】",JSON.toJSONString(map),JSON.toJSONString(staticCodePayVo));
            return ResultUtil.error(ResultEnum.Err_900);
        }
        String tradeNo = String.format("ZS%s%s%s",staticCodePayVo.getDeviceNo(), DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN), cn.hutool.core.util.RandomUtil.randomInt(1000,9999));
        QrCardPayRequest qrCardPayRequest=new QrCardPayRequest();

        qrCardPayRequest.setMachNo(staticCodePayVo.getDeviceNo());
        qrCardPayRequest.setCompanyId(staticCodePayVo.getComId());
        qrCardPayRequest.setAuthCode(user.getPId().toString());
        qrCardPayRequest.setTradeNo(tradeNo);
        qrCardPayRequest.setAmount(amount);  //消费金额
        qrCardPayRequest.setType(7);
        return  payHandleClientService.getPayCard(qrCardPayRequest);
    }
    // 公众号支付通道（/getRechargePayWay）
    @PostMapping(WxServiceUrl.URL_getRechargePayWay)
    public Result getRechargePayWay(@RequestBody Map<String,Object> map){
        GzhUserInfo userInfo  = (GzhUserInfo)map.get("userInfo");

        Long merchId =0l;

        if(map.get("merchId")!=null){
            merchId= ((Integer) map.get("merchId")).longValue();
//            merchId= Long.valueOf(map.get("merchId").toString());
        }

        if(merchId<=0l){
            //comId 74 还是走单位  暂时注释 TODO
            try {
                String code = (String) map.get("code");
                if(!CommonUtil.isNull(code)){
                    StaticCodePayVo staticCodePayVo = StaticCodePayUtil.getCodeInfo(code);
                    userInfo.setComId(staticCodePayVo.getComId());
                    if (staticCodePayVo == null) {
                        return ResultUtil.error(ResultEnum.Err_3072);
                    }
                    if(staticCodePayVo.getType()!=1){
                        return ResultUtil.error(ResultEnum.Err_3073);
                    }
                    //TODO  1 固定本单位  2用指定通道
                    Integer type = 2;
                    Result result4 = companyClientService.getCompanyConfig(staticCodePayVo.getComId(),"gzhOcom");
                    if(result4.getCode()==200) {
                        List<EntityCompanyConfig> companyConfigList = JSON.parseArray(JSON.toJSONString(result4.getData()), EntityCompanyConfig.class);
                        if(companyConfigList !=null && companyConfigList.size()>0
                                && companyConfigList.get(0).getConfig().equals("true")){
                            type = 1;
                        }
                    }
                    Result result2 = payHandleClientService.getUsefuleMerchPayInfo(staticCodePayVo.getComId(), staticCodePayVo.getDeviceNo(), type);
                    EntiyXfMerchPayInfo entiyXfMerchPayInfo = JSONObject.parseObject(JSONObject.toJSONString(result2.getData()),EntiyXfMerchPayInfo.class);
                    merchId = entiyXfMerchPayInfo.getMerchId().longValue();
                }
            }catch (Exception e){

            }
        }


        if(userInfo.getComId() == null || userInfo.getComId() ==0l){
            return ResultUtil.error(ResultEnum.Err_301);
        }
        Result result = payConfigClientService.getRechargePayWay(userInfo.getComId(),merchId,1);
        log.info("公众号支付通道（/getRechargePayWay）请求参数:{{}}{{}}{{}}",map ,merchId,result);

        return result;
    }

    // 公众号支付-充值规则（/getRechargeRule）
    @PostMapping(WxServiceUrl.URL_getRechargeRule)
    public Result getRechargeRule(@RequestBody Map<String,Object> map){
        log.info("公众号支付通道（/getRechargeRule）请求参数:{{}}",map);
        GzhUserInfo userInfo  = (GzhUserInfo)map.get("userInfo");
        return payConfigClientService.getRechargeRule(userInfo.getComId(),map.get("subAccount")==null?0:Integer.parseInt(map.get("subAccount").toString()));
    }

    //查单
    @PostMapping(WxServiceUrl.URL_Check)
    public Result Check(Long comId,String orderNo){
        log.info("公众号-查询（/Check）请求参数:【{}】【{}】",comId,orderNo);
//        payService.check(comId,orderNo);

        //4. mq延时查询  改异步
        Gson gson =new Gson();
        CheckVo checkVo=new CheckVo();
//        checkVo.setMachNo(staticCodePayVo.getDeviceNo());
        checkVo.setCompanyId(comId);
        checkVo.setOutTradeNo(orderNo);
        activeQuiryProduct.sendDelayMessage( gson.toJson(checkVo));

        return ResultUtil.success();
    }


    @Autowired
    ActiveQuiryProduct activeQuiryProduct;

    // 公众号回调地址  https://mj.ocomtraffic.com/ugcapi/callback

    @PostMapping(WxServiceUrl.URL_Callback)
    public Result callback(@RequestBody Result result){
        if(result.getData().toString().contains("notificationType")){
            log.info("收到建行签约回调 64BdHowr ， map 【{}】",result);
            JHcallbackVo jHcallbackVo = JSON.parseObject(JSON.toJSONString(result),JHcallbackVo.class);
            log.info("收到建行签约回调 Fy37zDZZ ，【{}】",jHcallbackVo);
            if (jHcallbackVo.getCode() == 200 && jHcallbackVo.getData().getResult().equals("success")) {
                //处理签约  解约  回调
                Result result2 = payConfigClientService.getPaySign(jHcallbackVo.getData().getOut_trade_no());
                if (result2.getCode() == 200) {
                    EntityXfSignOrder entityXfSignOrder = JSON.parseObject(JSON.toJSONString(result2.getData()), EntityXfSignOrder.class);
                    if (jHcallbackVo.getData().getNotificationType().equals("signing")) {
                        entityXfSignOrder.setStatus(2);
                    }
                    if (jHcallbackVo.getData().getNotificationType().equals("rescind")) {
                        entityXfSignOrder.setStatus(3);
                    }
//				signing-签约通知
//				rescind-解约通知
//				pre_order-预下单
                    entityXfSignOrder.setSignNo(jHcallbackVo.getData().getContract_id());
                    payConfigClientService.updatePaySign(entityXfSignOrder);
                }
            }
            return ResultUtil.success();
        }
        log.info("公众号支付-支付收到回调 E976X9Sx 【{}】",result );
        Boolean b  = payService.callback(result);
        if(!b){
            return ResultUtil.error(ResultEnum.Err_4005);
        }
        return ResultUtil.info(200,"success");
    }

//    @PostMapping(WxServiceUrl.URL_signCallback)
    public Result signCallback(@RequestBody Result result){
        Boolean b  = payService.callback1(result);
        if(!b){
            return ResultUtil.error(ResultEnum.Err_4005);
        }
        return ResultUtil.success();
    }



    @PostMapping(WxServiceUrl.URL_payList)
    public Result getUserPayList(@RequestBody Map<String,Object> map){
        GzhUserInfo userInfo  = (GzhUserInfo)map.get("userInfo");

        Integer page =1;
        Integer size =30;
        String startTime = DateUtils.getDate()+" 00:00:00";
        String endTime = DateUtils.getDate()+" 23:59:59";
        List<String> consState = new ArrayList<>();


        try {
            page = (Integer) map.get("page");
            size = (Integer) map.get("size");
            startTime = (String) map.get("startTime");
            endTime = (String) map.get("endTime");
            if(ObjectUtil.isNotEmpty((String) map.get("consState"))){
                consState = Arrays.asList(((String) map.get("consState")).split(","));
            }

        }catch (Exception e){

        }

        JSONObject jsonObject =new JSONObject();
        jsonObject.put("comId",userInfo.getComId());
        jsonObject.put("pId",userInfo.getPId());
        jsonObject.put("page",page);
        jsonObject.put("size",size);
        jsonObject.put("startTime",startTime);
        jsonObject.put("endTime",endTime);
        jsonObject.put("consStates",consState);
        Result result1 = xfRecordFeign.getConsumeDetail(jsonObject);

        ConsumeDetailVo mjRecords1 = JSON.parseObject(JSON.toJSONString(result1.getData()),ConsumeDetailVo.class);

        for (int i =0 ; i<mjRecords1.getList().size();i++){
            Object o = mjRecords1.getList().get(i);
            JSONObject mjRecord= JSON.parseObject(JSON.toJSONString(o));
            mjRecord.put("chargeBalance",(double) (mjRecord.getInteger("chargeBalance")/100.0));
            mjRecord.put("chargeMoney",(double) (mjRecord.getFloatValue("chargeMoney")/100.0));
            mjRecord.put("consMoney",(double) (mjRecord.getFloatValue("consMoney")/100.0));
            mjRecord.put("consStateId", mjRecord.getIntValue("consState"));
            mjRecord.put("consState", ConsStateEnum.getValueByKey(mjRecord.getIntValue("consState")));
            mjRecord.put("opType", OpTypeEnum.getName(mjRecord.getIntValue("opType")));
            mjRecord.put("opTypeDiff", OpTypeDiffEnum.getName(mjRecord.getIntValue("opTypeDiff")));
            mjRecord.put("payAmount",(double) (mjRecord.getFloatValue("payAmount")/100.0));
            mjRecord.put("payState", PayStateEnum.getValueByKey(mjRecord.getIntValue("payState")));
            mjRecord.put("realMoney",(double) (mjRecord.getFloatValue("realMoney")/100.0));
            mjRecord.put("subBalance",(double) (mjRecord.getFloatValue("subBalance")/100.0));
            mjRecord.put("subMoney",(double) (mjRecord.getFloatValue("subMoney")/100.0));
            mjRecord.put("subsidy",(double) (mjRecord.getFloatValue("subsidy")/100.0));
            mjRecords1.getList().set(i,mjRecord);
        }
        return ResultUtil.success(mjRecords1);

    }


    @PostMapping(WxServiceUrl.URL_serviceCharges)
    public Result serviceCharges(@RequestBody ServiceChargesVo serviceChargesVo){
        Gson gson =new Gson();
        String mqKey = "MqSimple:serviceCharges:"+ RandomUtil.getRandomString(20);
        redisUtil.set(mqKey,serviceChargesVo,3700l);
        serviceChargesProduct.sendDelayMessage(mqKey);
        return ResultUtil.success();
    }


    @PostMapping(WxServiceUrl.URL_checkWithhold)
    public Result checkWithhold(@RequestBody Map<String,Object> map) {

        HttpServletRequest request= ContextUtils.getRequest();
        String userAgent = request.getHeader("User-Agent");
        if(!userAgent.contains("WeChat") && !userAgent.contains("MicroMessenger") ){
            return ResultUtil.error(ResultEnum.Err_3111);
        }

        GzhUserInfo userInfo = (GzhUserInfo) map.get("userInfo");
        Integer merchId  = (Integer) map.get("merchId");

        if (!redisUtil.lock("checkWithhold:comId:" + userInfo.getComId() +"#merchId:"+merchId+"#pId:"+userInfo.getPId(), 120)) {
            return ResultUtil.error(ResultEnum.Err_3110);
        }

        CheckPayRequest checkPayRequest =new CheckPayRequest();
        checkPayRequest.setCompanyId(userInfo.getComId());
        checkPayRequest.setPId(userInfo.getPId());
        checkPayRequest.setDeviceNo(userInfo.getAppId());
        checkPayRequest.setMerchId(merchId.longValue());
        checkPayRequest.setOrderNo(System.currentTimeMillis()+RandomUtil.generateNumber(10)+"test");
        Result result =  payHandleClientService.checkWithhold(checkPayRequest);

        if (result.getCode() == 200) {
            String mqKey = "MqSimple:checkWithhold:" + RandomUtil.getRandomString(20);
            QrCodeRefundRequest qrCodeRefundRequest = new QrCodeRefundRequest();
            qrCodeRefundRequest.setCompanyId(userInfo.getComId());
            qrCodeRefundRequest.setMachNo("00000000");
            qrCodeRefundRequest.setOrigTradeNo(checkPayRequest.getOrderNo());
            qrCodeRefundRequest.setTradeNo(System.currentTimeMillis() + RandomUtil.generateNumber(8) + "refund");
            qrCodeRefundRequest.setRefundAmount(1);
            redisUtil.set(mqKey, qrCodeRefundRequest, 60l * 10l * 1000l);
            checkWithholdRefundProduct.sendDelayMessage(mqKey);
        }

        return result;
    }


    //用户退款接口
    @PostMapping(WxServiceUrl.Url_gzhrechageList)
    public Result gzhrechageList(@RequestBody Map map) {
        GzhRefundQueryRequest request = JSON.parseObject(JSON.toJSONString(map), GzhRefundQueryRequest.class);
        GzhUserInfo user = request.getUserInfo();
        request.setComId(user.getComId());
        request.setPId(user.getPId());
        request.setPayState(-1);
        request.setConsState(10);
        request.setStartTime(DateUtils.addDays(new Date(),-60));
        return payConfigClientService.gzhRefunding(request);
    }


    //用户退款接口
    @PostMapping(WxServiceUrl.Url_rechargeRefund)
    public Result rechargeRefund(@RequestBody Map map) {
        UgcRerchargeRefundRequest request = JSON.parseObject(JSON.toJSONString(map), UgcRerchargeRefundRequest.class);
        GzhUserInfo user = request.getUserInfo();

        String tradeNoRedis = "Gzh:Refund" + user.getComId() + ":" + user.getPId() ;
        if (!redisUtil.lock(tradeNoRedis,  30)) {
            //点击太快
            return ResultUtil.error(ResultEnum.Err_4102);
        }

        GzhRechageRefundRequest gzhRechageRefundRequest= (GzhRechageRefundRequest) request;
        request.setComId(user.getComId());
        String ord = RandomUtil.generateNumber(18);
        request.setTradeNo(DateUtils.dateTimeNow()+ord);
        return payHandleClientService.gzhRechageRefund(gzhRechageRefundRequest);
    }


//    public static void main(String[] args){
//        for (int i=0;i<20;i++){
//            System.out.println(RandomUtil.generateNumber(18));
//        }
//    }



    //兰州银行  前端接收签约解约
    @PostMapping(WxServiceUrl.URL_signCallback)
    public Result signCallback(@RequestBody Map<String,Object> map) {
        log.info("收到兰州银行签约回调   123isQ0v， map 【{}】",map);
        SignCallbackVo signCallbackVo = JSON.parseObject(JSON.toJSONString(map),SignCallbackVo.class);
   //     log.info("收到建行签约回调，【{}】",signCallbackVo);

        if(!signCallbackVo.getResult().equals("success")){
            return ResultUtil.success();
        }

        if(CommonUtil.isNull(signCallbackVo.getSignOrderNo())){
            return ResultUtil.success();
        }

        //处理签约  解约  回调
        Result<EntityXfSignOrder> result = payConfigClientService.getPaySign(signCallbackVo.getSignOrderNo());

        if (result.getCode() == 200) {
            try {
                Result<EntityWechatAppInfo> wxInfo = payConfigClientService.getWxInfo(result.getData().getComId(), result.getData().getMerchId().longValue());
                if (wxInfo.getCode() != 200) {
                    return wxInfo;
                }
                signCallbackVo.setName(Sm2Utils.getSm2Decry(signCallbackVo.getName(),wxInfo.getData().getRemark()));
                signCallbackVo.setIdCrdNo(Sm2Utils.getSm2Decry(signCallbackVo.getIdCrdNo(),wxInfo.getData().getRemark()));
                signCallbackVo.setOrdrNo(Sm2Utils.getSm2Decry(signCallbackVo.getOrdrNo(),wxInfo.getData().getRemark()));
            } catch (Exception e) {
                return ResultUtil.success();
            }
        }

        if (result.getCode() == 200) {
            EntityXfSignOrder entityXfSignOrder = result.getData();
            entityXfSignOrder.setStatus(2);
//				signing-签约通知
//				rescind-解约通知
//				pre_order-预下单
            if(entityXfSignOrder.getSignType()==1){
                //1姓名 #  2手机号 # 3身份证 # 4签约号
                String signNo = signCallbackVo.getName()+"#0#"+signCallbackVo.getIdCrdNo()+"#" + signCallbackVo.getOrdrNo();
                entityXfSignOrder.setSignNo(signNo);
            }
            payConfigClientService.updatePaySign(entityXfSignOrder);

            if(entityXfSignOrder.getSignType()==1){
                return ResultUtil.info(200,"签约成功");
            }else{
                return ResultUtil.info(200,"解约成功");
            }
        }
        return ResultUtil.success();
    }


}